﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Tomasulo_Simulator
{
    public partial class Form1 : Form
    {
        UserSettings settings;
        Memory memory;

        public enum HitPolicy
        {
            WriteBack, WriteThrough
        };

        public enum MissPolicy
        {
            WriteAllocate, WriteAround
        };

        //Main Memory
        int MemorySize = 1024;
        int MemoryAccessTime = 100;
        int DataAddress = 0;
        int ProgramAddress = 512;

        //L1 Instruction Cache
        int L1ILineSize = 16;
        int L1ILines = 8;
        int L1IAssociativity = 2;
        int L1IAccessTime = 2;

        //L1 Data Cache
        int L1DLineSize = 16;
        int L1DLines = 8;
        int L1DAssociativity = 2;
        int L1DAccessTime = 2;
        int L1HitPolicy = (int)HitPolicy.WriteBack;
        int L1MissPolicy = (int)MissPolicy.WriteAllocate;

        //L2 Instruction Cache
        int L2DLineSize = 16;
        int L2DLines = 8;
        int L2DAssociativity = 2;
        int L2DAccessTime = 2;
        int L2HitPolicy = (int)HitPolicy.WriteBack;
        int L2MissPolicy = (int)MissPolicy.WriteAllocate;

        //L3 Instruction Cache
        int L3DLineSize = 16;
        int L3DLines = 8;
        int L3DAssociativity = 2;
        int L3DAccessTime = 2;
        int L3HitPolicy = (int)HitPolicy.WriteBack;
        int L3MissPolicy = (int)MissPolicy.WriteAllocate;

        //Tomasulo w/ Speculation variables
        int ROBEntries = 3;
        int ASUnits = 2;
        int ASCycles = 2;
        int MulUnits = 1;
        int MulCycles = 5;
        int DivUnits = 1;
        int DivCycles = 10;
        int InstructionBuffer = 4;

        int NumOfLevels = 1;
        int NumOfReservationStations = 6;
        String Data = "";
        String Program = "";

        public Form1()
        {
            InitializeComponent();
            settings = new UserSettings();
            memory = new Memory(MemorySize);
            settings.VisibleChanged += settings_VisibleChanged;
            settings.textBox1.TextChanged +=new EventHandler(MemorySize_TextChanged);
            this.Text = "Tomasulo Simulator";
        }

        void settings_VisibleChanged(object sender, EventArgs e)
        {
            if(!settings.Visible)
            {
                NumOfLevels = settings.radioButton3.Checked ? 3 : settings.radioButton2.Checked ? 2 : 1;
                NumOfReservationStations = Convert.ToInt32(settings.textBox29.Text);

                ASUnits = Convert.ToInt32(settings.textBox9.Text);
                ASCycles = Convert.ToInt32(settings.textBox14.Text);

                MulUnits = Convert.ToInt32(settings.textBox10.Text);
                MulCycles = Convert.ToInt32(settings.textBox15.Text);

                DivCycles = Convert.ToInt32(settings.textBox16.Text);
                DivUnits = Convert.ToInt32(settings.textBox13.Text);

                InstructionBuffer = Convert.ToInt32(settings.textBox12.Text);
                ROBEntries = Convert.ToInt32(settings.textBox11.Text);

                L1ILineSize = Convert.ToInt32(settings.textBox7.Text);
                L1ILines = Convert.ToInt32(settings.textBox8.Text);
                L1IAssociativity = Convert.ToInt32(settings.textBox6.Text);
                L1IAccessTime = Convert.ToInt32(settings.textBox5.Text);

                L1DLineSize = Convert.ToInt32(settings.textBox19.Text);
                L1DLines = Convert.ToInt32(settings.textBox20.Text);
                L1DAssociativity = Convert.ToInt32(settings.textBox18.Text);
                L1DAccessTime = Convert.ToInt32(settings.textBox17.Text);
                L1HitPolicy = (int)settings.comboBox1.SelectedIndex;
                L1MissPolicy = (int)settings.comboBox2.SelectedIndex;

                L2DLineSize = Convert.ToInt32(settings.textBox23.Text);
                L2DLines = Convert.ToInt32(settings.textBox24.Text);
                L2DAssociativity = Convert.ToInt32(settings.textBox22.Text);
                L2DAccessTime = Convert.ToInt32(settings.textBox21.Text);
                L2HitPolicy = (int)settings.comboBox3.SelectedIndex;
                L2MissPolicy = (int)settings.comboBox4.SelectedIndex;

                L3DLineSize = Convert.ToInt32(settings.textBox27.Text);
                L3DLines = Convert.ToInt32(settings.textBox28.Text);
                L3DAssociativity = Convert.ToInt32(settings.textBox26.Text);
                L3DAccessTime = Convert.ToInt32(settings.textBox25.Text);
                L3HitPolicy = (int)settings.comboBox5.SelectedIndex;
                L3MissPolicy = (int)settings.comboBox6.SelectedIndex;

                MemorySize = Convert.ToInt32(settings.textBox1.Text);
                ProgramAddress = Convert.ToInt32(settings.textBox2.Text);
                DataAddress = Convert.ToInt32(settings.textBox3.Text);
                MemoryAccessTime = Convert.ToInt32(settings.textBox4.Text);
            }
            else
            {
                settings.textBox29.Text = NumOfReservationStations + "";

                settings.textBox9.Text = ASUnits + "";
                settings.textBox14.Text = ASCycles + "";

                settings.textBox10.Text =  MulUnits + "";
                settings.textBox15.Text = MulCycles + "";

                settings.textBox16.Text = DivCycles + "";
                settings.textBox13.Text = DivUnits + "";

                settings.textBox12.Text = InstructionBuffer + "";
                settings.textBox11.Text = ROBEntries + "";

                settings.textBox7.Text = L1ILineSize + "";
                settings.textBox8.Text = L1ILines + "";
                settings.textBox6.Text = L1IAssociativity + "";
                settings.textBox5.Text = L1IAccessTime + "";

                settings.textBox19.Text = L1DLineSize + "";
                settings.textBox20.Text = L1DLines + "";
                settings.textBox18.Text = L1DAssociativity + "";
                settings.textBox17.Text = L1DAccessTime + "";

                settings.textBox23.Text = L2DLineSize + "";
                settings.textBox24.Text = L2DLines + "";
                settings.textBox22.Text = L2DAssociativity + "";
                settings.textBox21.Text = L2DAccessTime + "";

                settings.textBox27.Text = L3DLineSize + "";
                settings.textBox28.Text = L3DLines + "";
                settings.textBox26.Text = L3DAssociativity + "";
                settings.textBox25.Text = L3DAccessTime + "";

                settings.textBox1.Text = MemorySize + "";
                settings.textBox2.Text = ProgramAddress + "";
                settings.textBox3.Text = DataAddress + "";
                settings.textBox4.Text = MemoryAccessTime + "";
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            settings.ShowDialog();
        }

        private void textBox1_TextChanged(object sender, EventArgs e)
        {
            Data = textBox1.Text;
        }

        private void MemorySize_TextChanged(object sender, EventArgs e)
        {
            memory = new Memory(MemorySize);
        }

        private void textBox2_TextChanged(object sender, EventArgs e)
        {
            Program = textBox2.Text;
        }

        private void button2_Click(object sender, EventArgs e)
        {
            String[] s = Data.Split('\n');
            int i, j;
            for (i = DataAddress, j = 0; j < s.Length; i++, j++)
            {
                memory.storeWord(s[j], i);
            }
            s = Program.Split('\n');
            for (i = ProgramAddress, j = 0; j < s.Length; i++, j++)
            {
                memory.storeWord(s[j], i);
            }
        }
    }
}
